package com.example.demo.javaTest;

import com.example.demo.entity.Student;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Reflect {
    @Test
    public void testClass() throws ClassNotFoundException {
        Class<Student> c1 = Student.class;
        System.out.println(c1.getName());
        System.out.println(c1.getSimpleName());

        Class c2 = Class.forName("com.example.demo.entity.Student");
        System.out.println(c1 == c2);

        Student s = new Student();
        Class c3 = s.getClass();
        System.out.println(c2 == c3);
    }

    @Test
    public void testConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Student> c = Student.class;

        //获取构造器及其操作
        Constructor<?>[] constructors = c.getConstructors();//不推荐，无法获取private
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName() + "---" + constructor.getParameterCount());
        }
        Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();//推荐
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName() + "---" + declaredConstructor.getParameterCount());
        }
        Constructor<Student> constructor = c.getConstructor();//不推荐，无法获取private
        System.out.println(constructor.getName() + "---" + constructor.getParameterCount());
        Constructor<Student> declaredConstructor = c.getConstructor();//推荐
        System.out.println(declaredConstructor.getName() + "---" + declaredConstructor.getParameterCount());
        //Constructor<?> declaredConstructor2 = c.getConstructor(String.class,int.class);//获取有参构造器，需填参数类型
        //System.out.println(declaredConstructor2.getName()+"---"+declaredConstructor2.getParameterCount());
        declaredConstructor.setAccessible(true);//暴力反射，private也能调用
        Student student = declaredConstructor.newInstance();
        System.out.println(student);
    }

    @Test
    public void testField() throws NoSuchFieldException, IllegalAccessException {
        Class<Student> c = Student.class;

        //获取成员变量及其操作
        Field[] fields = c.getFields();//不推荐，无法获取private
        for (Field field : fields) {
            System.out.println(field.getName() + "---" + field.getType());
        }
        Field[] declaredFields = c.getDeclaredFields();//推荐
        for (Field field : declaredFields) {
            System.out.println(field.getName() + "---" + field.getType());
        }
        //Field f = c.getField("name");//不推荐，无法获取private
        //System.out.println(f.getName() + "---" + f.getType());
        Field df = c.getDeclaredField("name");//推荐
        System.out.println(df.getName() + "---" + df.getType());
        df.setAccessible(true);//暴力反射，private也能调用
        Student student = new Student();
        df.set(student, "name");
        System.out.println(student);
        String name = (String) df.get(student);
        System.out.println(name);
    }

    @Test
    public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<Student> c = Student.class;

        //获取成员方法及其操作
        Method[] methods = c.getMethods();//不推荐，无法获取private
        for (Method method : methods) {
            System.out.println(method.getName() + "-" + method.getParameterCount() + "-" + method.getReturnType());
        }
        Method[] declaredMethods = c.getDeclaredMethods();//推荐
        for (Method method : declaredMethods) {
            System.out.println(method.getName() + "-" + method.getParameterCount() + "-" + method.getReturnType());
        }
        Method m = c.getMethod("hashCode");//不推荐，无法获取private
        System.out.println(m.getName() + "-" + m.getParameterCount() + "-" + m.getReturnType());
        Method dm = c.getDeclaredMethod("hashCode");//推荐
        System.out.println(dm.getName() + "-" + dm.getParameterCount() + "-" + dm.getReturnType());
        dm.setAccessible(true);//暴力反射，private也能调用
        Student student = new Student();
        Object result = dm.invoke(student);
        System.out.println(result);
    }

    public void saveObject(Object obj) throws IllegalAccessException {
        Class c = obj.getClass();
        String cName = c.getSimpleName();
        Field[] fields = c.getDeclaredFields();
        for (Field field:fields){
            String name = field.getName();
            field.setAccessible(true);
            String value = field.get(obj)+ "";
            System.out.println(name+"-"+value);
        }
    }
}
